package org.com.yz.dubbo.service.impl;

import cn.hutool.core.date.DateTime;
import com.alibaba.dubbo.config.annotation.Service;
import org.com.yz.common.config.ConfigureTest;
import org.com.yz.common.util.*;
import org.com.yz.dal.dao.mapper.DepositTransactionMapper;
import org.com.yz.dal.dao.model.*;
import org.com.yz.dubbo.api.service.IBalanceQueryService;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

/**
 * @ClassName BalanceQueryServiceImpl
 * @Author wzc
 * @Date 2018/8/6 14:12
 **/


@Service(version = "1.0.0")
public class BalanceQueryServiceImpl implements IBalanceQueryService {


    private static Logger log = LoggerFactory.getLogger(BalanceQueryServiceImpl.class);

    @Autowired
    private DepositTransactionMapper depositTransactionMapper;


    @Override
    public  BalanceQuery  balanceQueryHandle(MchConfig mchConfig,String outTrn) {
        BalanceQuery  balanceQuery= doBalanceQueryPost(mchConfig);
        //插入事务表
        DepositTransaction depositTransaction = new DepositTransaction( );
        depositTransaction.setMchNo(mchConfig.getMchNo( ));
        depositTransaction.setTransactionNo(UUID.randomUUID( ).toString( ).replace("-", "").toLowerCase( ));//事务号
        depositTransaction.setOutTransNo(outTrn);//外部追踪号
        depositTransaction.setIdMchAccntChargeUp(0);
        depositTransaction.setCreateTime(new DateTime( ));//创建时间
        depositTransaction.setTransactionType("mchaccnt.balance.query");//事务类型
        depositTransaction.setUpdateTime(new DateTime( ));//更新时间
        depositTransactionMapper.insert(depositTransaction);
        return balanceQuery;
    }


    /**
     * 发送报文请求
     *
     * @param date
     * @return
     */
    public BalanceQuery doBalanceQueryPost(MchConfig mchConfigSupser) {
        BalanceQuery  balanceQuery=null;
        try {
            URL url = new URL(mchConfigSupser.getPay_url( ));
            URLConnection con = url.openConnection( );
            con.setDoOutput(true);
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");

            OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream( ));
            String xmlInfo = getXmlInfo( mchConfigSupser);
            log.info("发送余额查询报文" + xmlInfo);
            out.write(new String(xmlInfo.getBytes("gbk")));
            out.flush( );
            out.close( );
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream( ), "gbk"));
            String results = "";
            int tmp;
            while ((tmp = br.read( )) != -1) {
                results += (char) tmp;
            }
           balanceQuery= requestXmlToObject(results);
        } catch (MalformedURLException e) {
            e.printStackTrace( );
        } catch (IOException e) {
            e.printStackTrace( );
            log.info("银行余额查询接口调用失败" + e.getMessage( ));
        } catch (Exception e) {
            log.info("银行余额查询报文返回解析失败" + e.getMessage( ));
        }
        return balanceQuery;
    }


    /**
     * 拼接报文
     *
     * @param
     * @return
     */
    private String getXmlInfo(MchConfig mchConfigSupser) {
        StringBuilder sb = new StringBuilder( );
        sb.append("<?xml version=\"1.0\" encoding=\"GBK\"?>");
        sb.append("    <FOX>");
        sb.append("    <SIGNONMSGSRQV1>");
        sb.append("        <SONRQ>");
        sb.append("           <DTCLIENT>" + cn.hutool.core.date.DateUtil.now( ) + "</DTCLIENT>");            //客户端日期时间
        sb.append("           <CID>" + mchConfigSupser.getCid( ) + "</CID>");                                                   //企业网银客户号，10位数字字符
        sb.append("           <USERID>" + mchConfigSupser.getUserid( ) + "</USERID>");                                         // 登录用户名，最长：20位
        sb.append("           <USERPASS>" + AES.getInstance( ).decrypt(mchConfigSupser.getUserpass( )) + "</USERPASS>");         //密码采用aes加密                      //登录密码，最长：30位
        sb.append("           <GENUSERKEY>N</GENUSERKEY>");                                        //是否需要服务器产生USERKEY,，填Y、N
        sb.append("         </SONRQ>");

        sb.append("</SIGNONMSGSRQV1>");
        sb.append("  <SECURITIES_MSGSRQV1>");
        sb.append("   <SCUSTSTMTTRNRQ>");
        sb.append("     <TRNUID>" + DateUtil.getSeqString( ) + RandomNum.createRandomString(4) + "</TRNUID>");   //客户端交易的唯一标志  YYYYMMDD+序号
        sb.append("   <SCUSTSTMTRQ>");
        sb.append("      <ACCTFROM>");
        sb.append("        <ACCTID>" + mchConfigSupser.getAcctid( ) + "</ACCTID>");           //付款人账户
        sb.append("      </ACCTFROM>");
        sb.append("  </SCUSTSTMTRQ>");
        sb.append("</SCUSTSTMTTRNRQ>");
        sb.append("</SECURITIES_MSGSRQV1>");
        sb.append("</FOX>");
        return sb.toString( );
    }


    /**
     * 解析返回的报文
     *
     * @param responseXml
     * @return
     * @throws Exception
     */
    public BalanceQuery requestXmlToObject(String responseXml) throws Exception {
        log.info("交易记录返回报文" + responseXml);
        Document document = DocumentHelper.parseText(responseXml);
        Element root = document.getRootElement( );  // 获得根节点；

        Element ele = root.element("SIGNONMSGSRSV1");
        Element ele1 = ele.element("SONRS");
        Element ele2 = ele1.element("STATUS");
        Element ele3 = ele2.element("CODE");
        Element ele6 = root.element("SECURITIES_MSGSRSV1");
        if (!"0".equals(ele3.getText( ))) {           //第一层返回状态
            Element messageEle = ele2.element("MESSAGE");
            log.info(messageEle.getText( ));
            return null;
        }
        Element ele7 = ele6.element("SCUSTSTMTTRNRS"); //第一层无错误才有第二层
        Element ele9 = ele7.element("STATUS");
        Element ele10 = ele9.element("CODE");
        if (!"0".equals(ele10.getText( ))) {           //返回第二层的状态
            Element messageEle = ele9.element("MESSAGE");
            log.info(messageEle.getText( ));
            return null;
        }
        Element ele11 = ele7.element("SCUSTSTMTRS");

        Element ele12 = ele11.element("ACCTFROM");
        Element acctid = ele12.element("ACCTID");

        Element ledgerbal = ele11.element("LEDGERBAL");
        Element balamt = ledgerbal.element("BALAMT");   //活期账户余额，和下面可用余额基本一致，除非存在贷款户等业务上冻结或被控制的金额，总账才会比可用大。
        Element dtasof = ledgerbal.element("DTASOF");  //日期

        Element availbal = ele11.element("AVAILBAL");
        Element balamt2 = availbal.element("BALAMT");   //可用余额

        BalanceQuery  balanceQuery=new BalanceQuery();
        balanceQuery.setAcctid(acctid.getText());    //付款账号
        balanceQuery.setBalamt(AmountUtil.convertDollar2Cent(balamt.getText()));    //总余额
        balanceQuery.setAvailableamt(AmountUtil.convertDollar2Cent(balamt2.getText()));   //可用余额
        balanceQuery.setDtasof(dtasof.getText());    //日期
        return balanceQuery;
    }


}
